﻿using AnesSystem.Controls;
using AnesSystem.Model;
using AnesSystem.Models;
using AnesSystem.Services;
using AnesSystem.Udp;
using AnesSystem.Util;
using Common;
using MongoDB.Bson;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace AnesSystem.ViewModels
{
    public class SecheduleMainCtrlViewModel : BaseViewModel<SecheduleMainCtrlViewModel>
    {
        #region Variables

        private string _preRoomId;
        private List<PatientLinkModel> allOperationList = new List<PatientLinkModel>();
        private ObservableCollection<ConfigRoomAndTaiShu> _displayConfigOperationRoomModelList;
        private ConfigRoomAndTaiShu _currentRoom;
        private DateTime _selDateTime = DateTime.Now;
        private DispatcherTimer timer;
        private bool isZDPT = true;
        private string search = "";

        #endregion

        #region Constructor
        public SecheduleMainCtrlViewModel()
        {
            _displayConfigOperationRoomModelList = new ObservableCollection<ConfigRoomAndTaiShu>();
            UdpMangager.Instance.ReceivedMsg += Instance_ReceivedMsg;
            InitalTimer();
        }

        #endregion

        #region Properties

        public PatientLinkModel SelectedSechduledP { get; set; }

        public ObservableCollection<ConfigRoomAndTaiShu> DisplayConfigOperationRoomModelList
        {
            get
            {
                return _displayConfigOperationRoomModelList;
            }

            set
            {
                _displayConfigOperationRoomModelList = value;
            }
        }

        public string Seach
        {
            get
            {
                return search;
            }

            set
            {
                NoSecheduledListCtrlViewModel.Instance.Seach = value;
                search = value;
                //SerchData();
            }
        }

        public List<PatientLinkModel> AllOperationList
        {
            get
            {
                return allOperationList;
            }

            set
            {
                allOperationList = value;
            }
        }

        public ConfigRoomAndTaiShu CurrentRoom
        {
            get
            {
                return _currentRoom;
            }

            set
            {
                if (_currentRoom != null)
                    _preRoomId = _currentRoom.ConfigOperationRoomModel.Name;
                _currentRoom = value;
            }
        }

        public DateTime SelDateTime
        {
            get
            {
                return _selDateTime;
            }

            set
            {
                _selDateTime = value;
                Refresh();
                RaisePropertyChanged("SelDateTime");
            }
        }

        public bool IsZDPT
        {
            get
            {
                return isZDPT;
            }
            set
            {
                isZDPT = value;
            }
        }


        #endregion

        #region Event

        #endregion

        #region Private Methods

        private void RefPaiTai()
        {
            if (isZDPT)
            {

            }
        }

        private void InitData()
        {
            DisplayConfigOperationRoomModelList.Clear();
            DateTime start = new DateTime(SelDateTime.Year, SelDateTime.Month, SelDateTime.Day);
            DateTime end = start.AddDays(1);
            allOperationList = PatientLinkService.Instance.GetOperationsByDay(start, end);
            foreach (var item in allOperationList)
            {
                item.Application.PropertyChanged -= PatientLink_PropertyChanged;
                item.Schedule.PropertyChanged -= PatientLink_PropertyChanged;
                item.Application.PropertyChanged += PatientLink_PropertyChanged;
                item.Schedule.PropertyChanged += PatientLink_PropertyChanged;
            }
            foreach (var Item in DataManager.Instance.ConfigOperationRoomModelList)
            {
                int taishu = 0;
                foreach (var item in allOperationList)
                {
                    if (Item.Name.Equals(item.Schedule.Pbssjh))
                    {
                        taishu++;
                    }
                }
                ConfigRoomAndTaiShu configRoomAndTaiShu = new ConfigRoomAndTaiShu();
                configRoomAndTaiShu.ConfigOperationRoomModel = Item;
                configRoomAndTaiShu.TotalTaiShu = taishu;
                DisplayConfigOperationRoomModelList.Add(configRoomAndTaiShu);
            }
        }

        private void InitalTimer()
        {
            int i = 10;
            timer = new DispatcherTimer();
            if (HospitalConfig.Instance.CurrentHospital.HospitalCode.Equals(HospitalConfig.HOSPITAL_CODE_CQ_NTZYY)||
                HospitalConfig.Instance.CurrentHospital.HospitalCode.Equals(HospitalConfig.HOSPITAL_CODE_CQ_FYBJY))
            {
                i = 20;
            }            
            timer.Interval = new TimeSpan(0, 0, i);
            timer.Tick += Timer_Tick;
        }

        private void SetTaiShu(PatientLinkModel patientLink, IEnumerable<PatientLinkModel> scheduledList)
        {
            ScheduleModel m = patientLink.Schedule;
            int pbts = m.PbtsInt;
            //新排台是否占用了其他病人的

            PatientLinkModel p = null;
            foreach (var item in scheduledList)
            {
                if (item.Id != patientLink.Id && item.Schedule.PbtsInt == m.PbtsInt)
                {
                    p = item;
                    break;
                }
            }

            if (p != null)
            {
                List<PatientLinkModel> tempList = new List<PatientLinkModel>();
                List<ObjectId> idList = new List<ObjectId>();
                if (isZDPT)
                {
                    p.Schedule.PropertyChanged -= PatientLink_PropertyChanged;
                    int maxpts = scheduledList.Count();
                    if (maxpts == 1)
                    {
                        p.Schedule.PbtsInt = 2;

                    }
                    else if (pbts == maxpts)
                    {
                        p.Schedule.PbtsInt = m.OldPbts;
                    }
                    else
                    {
                        p.Schedule.PbtsInt = pbts + 1;
                        int nextPbts = p.Schedule.PbtsInt + 1;
                        int count = scheduledList.Count();
                        for (int i = 0; i < count; i++)
                        {
                            PatientLinkModel np = scheduledList.ElementAt(i);
                            if (!np.Id.Equals(p.Id) && np.Schedule.PbtsInt >= pbts + 1 && !idList.Contains(np.Id))
                            {
                                np.Schedule.PropertyChanged -= PatientLink_PropertyChanged;
                                np.Schedule.PbtsInt = nextPbts;
                                nextPbts++;
                                np.Schedule.PropertyChanged += PatientLink_PropertyChanged;
                                tempList.Add(np);
                                idList.Add(np.Id);
                            }
                        }
                    }
                }
                else
                {
                    p.Schedule.PbtsInt = m.OldPbts;
                }
                tempList.Add(p);
                idList.Add(p.Id);
                p.Schedule.PropertyChanged += PatientLink_PropertyChanged;

                if (idList.Count == 1)
                {
                    var tempP = PatientLinkService.Instance.GetObjById(p.Id.ToString());
                    tempP.Schedule.PbtsInt = p.Schedule.PbtsInt;
                    PatientLinkService.Instance.Update(tempP);
                }
                else
                {
                    List<PatientLinkModel> insertList = new List<PatientLinkModel>();
                    foreach (var item in tempList)
                    {
                        var tempP = PatientLinkService.Instance.GetObjById(item.Id.ToString());
                        tempP.Schedule.PbtsInt = p.Schedule.PbtsInt;
                        insertList.Add(tempP);
                    }
                    HelperManager.Instance.MongoDB.BatchDelete<ObjectId>(idList, "patientLink");
                    HelperManager.Instance.MongoDB.BatchInsert(insertList, "patientLink");
                }
            }
            SecheduledListCtrlViewModel.Instance.ChangeRightCollection();
        }

        #endregion

        #region Public/Protected Methods

        public void GetPatientLinksFromHIS()
        {
            Task.Factory.StartNew(delegate
            {
                UdpMangager.Instance.SendUdpServerMsg(ServiceSign.OPERATION_ADD, new UdpModel());
                timer.Start();//执行查询方法的线程  
            });
            MainPageCommonViewModel.Instance.WaitCtrlVisibility = Visibility.Visible;
        }

        public override void Refresh()
        {
            InitData();
            RefUI();
        }

        public override void UdpRef(PatientLinkModel pm)
        {
            bool isRef = false;
            //var p= allOperationList.First(item => item.Id.Equals(pm.Id) && (
            //        (item.Schedule.PbtsInt != pm.Schedule.PbtsInt) ||
            //        !item.Application.Detailstatus.Equals(pm.Application.Detailstatus)) ||
            //        (item.Patient.Status == pm.Patient.Status || (item.Patient.Status != null && !item.Patient.Status.Equals(pm.Patient.Status))));
            //if (p != null)
            //{
            //    p = pm;
            //}
            //RefUI();
            foreach (var item in allOperationList)
            {
                if (item.Id.Equals(pm.Id) && (
                    (item.Schedule.PbtsInt != pm.Schedule.PbtsInt) ||
                    !item.Application.Detailstatus.Equals(pm.Application.Detailstatus)) ||
                    (item.Patient.Status == pm.Patient.Status || (item.Patient.Status != null && !item.Patient.Status.Equals(pm.Patient.Status))))
                {
                    isRef = true;
                    break;
                }
            }
            if (isRef)
            {
                Refresh();
            }
        }

        public void AddSecheduled(PatientLinkModel patientLinkModel)
        {
            patientLinkModel.Application.PropertyChanged -= PatientLink_PropertyChanged;
            patientLinkModel.Schedule.PropertyChanged -= PatientLink_PropertyChanged;
            if (!string.IsNullOrEmpty(_preRoomId) &&
                patientLinkModel.Application.Detailstatus == Constants.OR_STATUS_FLAG_SCHEDULED &&
                !string.IsNullOrEmpty(patientLinkModel.Schedule.Pbssjh))
            {
                DisplayConfigOperationRoomModelList.First(O => O.ConfigOperationRoomModel.Name.Equals(_preRoomId)).TotalTaiShu--;
            }
            else
            {
                patientLinkModel.Application.Detailstatus = Constants.OR_STATUS_FLAG_SCHEDULED;
            }

            patientLinkModel.Schedule.Pbssjh = CurrentRoom.ConfigOperationRoomModel.Name;
            CurrentRoom.TotalTaiShu++;
            patientLinkModel.Schedule.PbtsInt = CurrentRoom.TotalTaiShu;
            patientLinkModel.Schedule.Jhsssj = patientLinkModel.Application.Yysssj;

            patientLinkModel.Application.PropertyChanged += PatientLink_PropertyChanged;
            patientLinkModel.Schedule.PropertyChanged += PatientLink_PropertyChanged;
            PatientLinkService.Instance.Update(patientLinkModel);
            HospitalReturnUtil.Instance.ReturnOperSecheduled2His(patientLinkModel);
        }

        public void AddSecheduled(IList list)
        {
            foreach (PatientLinkModel item in list)
            {
                AddSecheduled(item);
            }
        }

        public void DeleteSecheduled(PatientLinkModel patientLinkModel)
        {
            patientLinkModel.Application.PropertyChanged -= PatientLink_PropertyChanged;
            patientLinkModel.Schedule.PropertyChanged -= PatientLink_PropertyChanged;

            patientLinkModel.Application.Detailstatus = Constants.OR_STATUS_FLAG_APPLIED;
            patientLinkModel.Schedule.Pbssjh = "";
            patientLinkModel.Schedule.PbtsInt = 0;
            patientLinkModel.Schedule.Jhsssj = patientLinkModel.Application.Yysssj;
            patientLinkModel.Schedule.Mzysbh1 = "";
            patientLinkModel.Schedule.Mzysbh2 = "";
            patientLinkModel.Schedule.Mzysbh3 = "";
            patientLinkModel.Schedule.Qxhsbh1 = "";
            patientLinkModel.Schedule.Xhhsbh1 = "";
            CurrentRoom.TotalTaiShu--;

            patientLinkModel.Application.PropertyChanged += PatientLink_PropertyChanged;
            patientLinkModel.Schedule.PropertyChanged += PatientLink_PropertyChanged;
            PatientLinkService.Instance.Update(patientLinkModel);
        }
        public void DeleteSecheduled(IList list)
        {
            foreach (PatientLinkModel item in list)
            {
                DeleteSecheduled(item);
            }
        }

        public void RefUI()
        {
            NoSecheduledListCtrlViewModel.Instance.Refresh();
            SecheduledListCtrlViewModel.Instance.Refresh();
        }

        public void PaiTai(PatientLinkModel patientLink, string roomId)
        {
            List<PatientLinkModel> scheduledList = PatientLinkService.Instance.GetScheduleTableOpersByRoomId(roomId);
            SetTaiShu(patientLink, scheduledList);
        }

        public void PaiTai(PatientLinkModel patientLink, List<PatientLinkModel> scheduledList)
        {
            SetTaiShu(patientLink, scheduledList);
        }

        public IEnumerable<PatientLinkModel> GetSechduledByRoomId()
        {
            try
            {
                if (CurrentRoom == null) return new List<PatientLinkModel>();
                IEnumerable<PatientLinkModel> list = AllOperationList.Where(O => CurrentRoom.ConfigOperationRoomModel.Name.Equals(O.Schedule.Pbssjh) && !O.Application.Detailstatus.Equals(Constants.OR_STATUS_FLAG_APPLIED)).OrderBy(O => O.Schedule.PbtsInt);
                if (!isZDPT)
                {
                    return list;
                }
                List<PatientLinkModel> tempList = new List<PatientLinkModel>();
                List<ObjectId> idList = new List<ObjectId>();
                bool isNeedUdate = false;
                for (int i = 0; i < list.Count(); i++)
                {
                    PatientLinkModel item = list.ElementAt(i);
                    item.Schedule.PropertyChanged -= PatientLink_PropertyChanged;
                    item.Application.PropertyChanged -= PatientLink_PropertyChanged;
                    int ts = i + 1;
                    int nextTs = ts + 1;
                    if (item.Schedule.PbtsInt != i + 1 && !idList.Contains(item.Id))
                    {
                        item.Schedule.PbtsInt = i + 1;
                        tempList.Add(item);
                        idList.Add(item.Id);
                        isNeedUdate = true;
                    }
                    item.Schedule.PropertyChanged += PatientLink_PropertyChanged;
                    item.Application.PropertyChanged += PatientLink_PropertyChanged;
                }
                if (idList.Count > 0 && isNeedUdate)
                {
                    HelperManager.Instance.MongoDB.BatchDelete<ObjectId>(idList, "patientLink");
                    HelperManager.Instance.MongoDB.BatchInsert(tempList, "patientLink");
                }

                return list;
            }
            catch (Exception ex)
            {
                Common.LogHelper.Error(this.GetType(), ex);
                return new List<PatientLinkModel>();
            }
        }

        #endregion

        #region EventHandlers

        private void PatientLink_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            PatientLinkModel model = PatientLinkService.Instance.GetObjById(SelectedSechduledP.Id.ToString());
            if (sender is ScheduleModel)
            {
                object value = SelectedSechduledP.Schedule.GetType().GetProperty(e.PropertyName).GetValue(SelectedSechduledP.Schedule);
                model.Schedule.GetType().GetProperty(e.PropertyName).SetValue(model.Schedule, value);
            }
            else if (sender is ApplicationModel)
            {
                object value = SelectedSechduledP.Application.GetType().GetProperty(e.PropertyName).GetValue(SelectedSechduledP.Application);
                model.Application.GetType().GetProperty(e.PropertyName).SetValue(model.Application, value);
            }
            PatientLinkService.Instance.Update(model);
            if (e.PropertyName.Equals("PbtsInt"))
            {
                SetTaiShu(SelectedSechduledP, SecheduledListCtrlViewModel.Instance.DisplayScheduledList);
            }
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            //            NoSecheduledListCtrlViewModel.Instance.Refresh();
            Refresh();
            MainPageCommonViewModel.Instance.WaitCtrlVisibility = Visibility.Collapsed;
            timer.Stop();
        }
        private void Instance_ReceivedMsg(object sender, UdpMsgAnalysisArgs e)
        {
            if (e.UdpMsgAnalysis.TimeOut.Equals("timeOut"))
            {

                MainPageCommonViewModel.Instance.WaitCtrlVisibility = Visibility.Collapsed;
            }
            else if (e.UdpMsgAnalysis.MethodId.Equals(Udp.ServiceSign.OPERATION_ADD))
            {
                MainPageCommonViewModel.Instance.WaitCtrlVisibility = Visibility.Collapsed;
            }
        }

        #endregion


        #region Command

        #region ChangeDoctorCommand


        #endregion

        #region OpenPopupCommand

        #endregion
        #endregion
    }
    public class ConfigRoomAndTaiShu : Common.ObservableObject
    {
        private ConfigOperationRoomModel _configOperationRoomModel;
        private int _totalTaiShu;
        private bool _isChecked=false;

        public ConfigOperationRoomModel ConfigOperationRoomModel
        {
            get
            {
                return _configOperationRoomModel;
            }

            set
            {
                _configOperationRoomModel = value;
                RaisePropertyChanged("ConfigOperationRoomModel");
            }
        }

        public int TotalTaiShu
        {
            get
            {
                return _totalTaiShu;
            }

            set
            {
                _totalTaiShu = value;
                RaisePropertyChanged("TotalTaiShu");
            }
        }
        public bool IsChecked
        {
            get
            {
                return _isChecked;
            }
            set
            {
                _isChecked = value;
                RaisePropertyChanged("IsChecked");
            }
        }
    }
}
